package se.webbzon.oschi01.gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.tree.TreePath;

import se.webbzon.oschi01.gui.MainModelEvent.Action;
import se.webbzon.oschi01.nbt.NBTException;
import se.webbzon.oschi01.nbt.Tag;
import se.webbzon.oschi01.singleton.Singletons;
import se.webbzon.oschi01.world.Chunk;
import se.webbzon.oschi01.world.Region;

public class WorldPanel extends JPanel {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -7055377429709666746L;
	
	private final JComboBox<se.webbzon.oschi01.world.Dimension> dimensionCombo;
	
	private final JComboBox<Region> regionCombo;
	
	private final JComboBox<Chunk> chunkCombo;
	
	private final JTree nbtTree;
	
	private Chunk selectedChunk = null;
	
	public WorldPanel(MainModel model) {
		model.addObserver(new ObserverImpl());
		setLayout(new BorderLayout(0,1));
		setPreferredSize(new Dimension(240,480));
		
		ActionListener listener = new ActionListenerImpl();
		JPanel upperPanel = new JPanel();
		upperPanel.setLayout(new GridLayout(7,1));
		upperPanel.add(new JLabel("Dimension"));
		dimensionCombo = new JComboBox<se.webbzon.oschi01.world.Dimension>();
		dimensionCombo.addActionListener(listener);
		upperPanel.add(dimensionCombo);
		upperPanel.add(new JLabel("Region"));
		regionCombo = new JComboBox<Region>();
		regionCombo.addActionListener(listener);
		upperPanel.add(regionCombo);
		upperPanel.add(new JLabel("Chunk"));
		chunkCombo = new JComboBox<Chunk>();
		chunkCombo.addActionListener(listener);
		upperPanel.add(chunkCombo);
		add(upperPanel,BorderLayout.NORTH);
		
		nbtTree = new JTree(new NBTTreeModel(null));
		try {
			nbtTree.setCellRenderer(new NBTTreeCellRenderer());
			nbtTree.addMouseListener(new MouseAdapterImpl());
		} catch (IOException e) {
			e.printStackTrace();
		}
		add(new JScrollPane(nbtTree,ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED),BorderLayout.CENTER);
	}
	
	private final class ObserverImpl implements Observer {

		@Override public void update(Observable o, Object arg) {
			if (o instanceof MainModel && arg instanceof MainModelEvent) {
				MainModel model = (MainModel) o;
				MainModelEvent e = (MainModelEvent) arg;
				Action a = e.getAction();
				if (a == Action.WORLD_CHANGED) {
					dimensionCombo.setModel(new DimensionComboBoxModel(model.getWorld()));
				} else if (a == Action.DIMENSION_CHANGED) {
					regionCombo.setModel(new RegionComboBoxModel(model.getDimension()));
				} else if (a == Action.REGION_CHANGED) {
					nbtTree.setModel(new NBTTreeModel(null));
					chunkCombo.setModel(new ChunkComboBoxModel(model.getRegion()));
				}
			}
		}
		
	}
	
	private final class MouseAdapterImpl extends MouseAdapter {
		
		@Override public void mousePressed(MouseEvent e) {
			if (SwingUtilities.isRightMouseButton(e)) {
				TreePath path = nbtTree.getPathForLocation(e.getX(),e.getY());
				Rectangle pathBounds = nbtTree.getUI().getPathBounds(nbtTree,path);
				if (pathBounds != null && pathBounds.contains(e.getX(),e.getY())) {
					Tag<?> tag = (Tag<?>) path.getLastPathComponent();
					nbtTree.setSelectionPath(path);
					NBTPopupMenu menu = new NBTPopupMenu(tag,Singletons.instance(MainFrame.class).getModel());
					menu.show(nbtTree,pathBounds.x,pathBounds.y + pathBounds.height);
				}
			}
		}
		
    }
	
	private final class ActionListenerImpl implements ActionListener {

		@Override public void actionPerformed(ActionEvent event) {
			Object source = event.getSource();
			Object obj;
			if (source == chunkCombo) {
				// change chunk
				obj = chunkCombo.getSelectedItem();
				if (obj == null)
					nbtTree.setModel(new NBTTreeModel(null));
				else if (obj instanceof Chunk) {
					selectedChunk = (Chunk) obj;
					try {
						Tag<?> root = selectedChunk.getRoot();
						nbtTree.setModel(new NBTTreeModel(root));
					} catch (NBTException e) {
						e.printStackTrace();
					}
				}
			} else if (source == regionCombo) {
				// change region
				obj = regionCombo.getSelectedItem();
				if (obj instanceof Region)
					Singletons.instance(MainFrame.class).getModel().setRegion((Region) obj);
			} else if (source == dimensionCombo) {
				// change region
				obj = dimensionCombo.getSelectedItem();
				if (obj instanceof se.webbzon.oschi01.world.Dimension)
					Singletons.instance(MainFrame.class).getModel().setDimension((se.webbzon.oschi01.world.Dimension) obj);
				
			}
		}
		
	}

}
